import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
import { supabase } from '../server'
import { logger } from '../utils/logger'

export interface AuthenticatedRequest extends Request {
  user?: {
    id: string
    email: string
    role?: string
    subscription_status?: string
  }
}

// Middleware to authenticate users using Supabase JWT
export async function authenticateUser(
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) {
  try {
    const authHeader = req.headers.authorization
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({
        success: false,
        message: 'Access token is required'
      })
    }

    const token = authHeader.substring(7) // Remove "Bearer " prefix

    // Verify the token with Supabase
    const { data: { user }, error } = await supabase.auth.getUser(token)

    if (error || !user) {
      logger.warn('Authentication failed', { 
        error: error?.message,
        ip: req.ip,
        userAgent: req.get('User-Agent')
      })
      return res.status(401).json({
        success: false,
        message: 'Invalid or expired access token'
      })
    }

    // Get user profile for additional information
    const { data: profile } = await supabase
      .from('user_profiles')
      .select('subscription_status')
      .eq('user_id', user.id)
      .single()

    // Attach user information to request
    req.user = {
      id: user.id,
      email: user.email!,
      role: user.role || 'user',
      subscription_status: profile?.subscription_status || 'free'
    }

    next()
  } catch (error) {
    logger.error('Authentication middleware error', { 
      error: error instanceof Error ? error.message : String(error),
      ip: req.ip
    })
    return res.status(500).json({
      success: false,
      message: 'Internal server error during authentication'
    })
  }
}

// Middleware to check if user has specific subscription level
export function requireSubscription(requiredLevel: string | string[]) {
  return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    const userSubscription = req.user?.subscription_status

    if (!userSubscription) {
      return res.status(403).json({
        success: false,
        message: 'Subscription information not available'
      })
    }

    const allowedLevels = Array.isArray(requiredLevel) ? requiredLevel : [requiredLevel]
    
    if (!allowedLevels.includes(userSubscription)) {
      return res.status(403).json({
        success: false,
        message: `This feature requires ${allowedLevels.join(' or ')} subscription`,
        required_subscription: allowedLevels,
        current_subscription: userSubscription
      })
    }

    next()
  }
}

// Middleware to check if user has admin role
export function requireAdmin(req: AuthenticatedRequest, res: Response, next: NextFunction) {
  if (req.user?.role !== 'admin') {
    return res.status(403).json({
      success: false,
      message: 'Admin access required'
    })
  }
  next()
}

// Middleware to validate API key for external integrations
export async function validateApiKey(req: Request, res: Response, next: NextFunction) {
  try {
    const apiKey = req.headers['x-api-key'] as string

    if (!apiKey) {
      return res.status(401).json({
        success: false,
        message: 'API key is required'
      })
    }

    // Check API key in database
    const { data: keyData, error } = await supabase
      .from('api_keys')
      .select('user_id, is_active, rate_limit, last_used')
      .eq('key_hash', apiKey)
      .eq('is_active', true)
      .single()

    if (error || !keyData) {
      logger.warn('Invalid API key used', { 
        apiKey: apiKey.substring(0, 8) + '...',
        ip: req.ip 
      })
      return res.status(401).json({
        success: false,
        message: 'Invalid API key'
      })
    }

    // Update last used timestamp
    await supabase
      .from('api_keys')
      .update({ last_used: new Date().toISOString() })
      .eq('key_hash', apiKey)

    // Attach user ID to request
    ;(req as AuthenticatedRequest).user = {
      id: keyData.user_id,
      email: '',
      role: 'api_user'
    }

    next()
  } catch (error) {
    logger.error('API key validation error', { 
      error: error instanceof Error ? error.message : String(error),
      ip: req.ip
    })
    return res.status(500).json({
      success: false,
      message: 'Internal server error during API key validation'
    })
  }
}

// Rate limiting middleware for different subscription tiers
export function subscriptionRateLimit(req: AuthenticatedRequest, res: Response, next: NextFunction) {
  const userSubscription = req.user?.subscription_status

  // Set different rate limits based on subscription
  const rateLimits = {
    free: 10,
    premium: 100,
    academic: 50,
    institutional: 1000
  }

  const limit = rateLimits[userSubscription as keyof typeof rateLimits] || rateLimits.free

  // Add rate limit information to headers
  res.setHeader('X-RateLimit-Limit', limit.toString())
  res.setHeader('X-Subscription-Level', userSubscription || 'free')

  next()
}

// Middleware to log user activity
export function logUserActivity(action: string) {
  return async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    try {
      if (req.user?.id) {
        await supabase
          .from('user_activity_logs')
          .insert({
            user_id: req.user.id,
            action,
            ip_address: req.ip,
            user_agent: req.get('User-Agent'),
            timestamp: new Date().toISOString(),
            request_path: req.path,
            request_method: req.method
          })
      }
      next()
    } catch (error) {
      // Don't fail the request if logging fails
      logger.error('Activity logging error', { 
        error: error instanceof Error ? error.message : String(error),
        userId: req.user?.id,
        action
      })
      next()
    }
  }
}